/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package jamjun.infra.web;

import com.google.gson.Gson;
import jamjun.infra.exception.ErrorContainer;
import jamjun.infra.exception.ErrorModel;
import jamjun.infra.lang.*;
import static jamjun.infra.web.CHelper.MappingRequestToObj;
import jamjun.infra.web.Result;
import jamjun.infra.web.View;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
 *
 * @author Java
 */
public class Controller extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        try{
            doDespatch(request,response);
        }catch(IOException | ServletException e){
            PrintWriter out = response.getWriter();
            out.print(e.toString());
        }
    }
    
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try{
            doDespatch(request,response);
        }catch(IOException | ServletException e){
            PrintWriter out = response.getWriter();
            out.print(e.toString());
        }
    }
    
    private void doDespatch(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        GSession.Request = request;
        GSession.Response=response;
        GSession.errorContainer = new ErrorContainer();
        GSession.errorContainer.errorList = new ArrayList<ErrorModel>();
        //load the AppTest at runtime
        //no paramater
        Class noparams[] = {};
        //String parameter
        Class[] paramString = new Class[1];	
        paramString[0] = String.class;
        //int parameter
        Class[] paramInt = new Class[1];
        paramInt[0] = Integer.TYPE;
        Class[] paramClasses = new Class[2];
        paramClasses[0] = HttpServletRequest.class;
        paramClasses[1] = HttpServletResponse.class;
        try{
                //String requestURL = request.getRequestURI();
                String action = request.getParameter("[ac]");
                if(JJString.IsNullOrEmty(action))
                {
                    throw new Exception("No parameter action [ac]");
                }
                //String[] parts = string.split("");
                String clientClassName = this.getClass().getName();
                Class cls = Class.forName(clientClassName);
                Object obj = cls.newInstance();
                //no paramater
                //call the printIt method
                //Method method = cls.getDeclaredMethod(action,paramClasses);
                Result result =null;
                List<Object> resultObj = new ArrayList<>();
                Method[] declaredMethods = cls.getDeclaredMethods();
                for (Method declaredMethod : declaredMethods) {
                    if (declaredMethod.getName().equals(action)) {
                        Parameter[] parameters = declaredMethod.getParameters();
                        //Object[] parameterObjs;
                        for (Parameter parameter : parameters) {
                            Annotation[] annotations = parameter.getDeclaredAnnotations();
                            Type paramType= parameter.getType();
                            String paramClsName =paramType.getTypeName();
                            Class paramCls = Class.forName(paramClsName);
                            Object paramObj =null;
                            Enum paramEnum;
                            if(paramType instanceof Class && ((Class<?>)paramType).isEnum()){
                                //Enum paramEnum;
                            }else{
                                paramObj = paramCls.newInstance();
                            }
                            for(Annotation annotation : annotations){
                                if(annotation instanceof jamjun.infra.annotation.Param){
                                    jamjun.infra.annotation.Param paramAnnotation = (jamjun.infra.annotation.Param) annotation;
                                    if(paramType.getTypeName().equals(String.class.getTypeName())){
                                        paramObj = GSession.getRequest().getParameter(paramAnnotation.name());
                                        resultObj.add(paramObj);
                                    }else if(paramType instanceof Class && ((Class<?>)paramType).isEnum()){
                                        //paramObj = GSession.getRequest().getParameter(paramAnnotation.name());
                                        paramEnum=Enum.valueOf(paramCls,GSession.getRequest().getParameter(paramAnnotation.name()));
                                        resultObj.add(paramEnum);
                                    }else{
                                        paramObj = MappingRequestToObj(paramObj,paramAnnotation.name(),GSession.getRequest());
                                        resultObj.add(paramObj);
                                    }
                                    
                                    System.out.println("name: " + paramAnnotation.name());
                                }
                            }
                             //Type type =parameter.getParameterizedType();
                            //String parameterName = parameter.getName();
                            // CHelper.MappingRequest(parameter, request);
                        }
                        //Object[] ObjecArr = 
                        result = (Result) declaredMethod.invoke(obj,resultObj.toArray());
                        
                        //result = (Result) declaredMethod.invoke(obj,resultObj);
                        break;
                    }
                }
                if(result == null){
                    throw new Exception("result not null");
                }
                
                //Class<?>[] param = method.getParameterTypes();
                //Result result = (Result) method.invoke(obj,request,response);
                if(GSession.errorContainer != null && GSession.errorContainer.errorList.size() > 0)
                {
                    response.setContentType("text/html;charset=UTF-8");
                    PrintWriter out = response.getWriter();
                    ErrorModel errorModel = GSession.getErrorContainer().errorList.stream().findFirst().get();
                    String msg = errorModel.errorKey + ":" + errorModel.errorMsg;
                    out.print(msg);
                }else{
                    if(result.getResultType() == ResultType.view){
                        response.setContentType("text/html;charset=UTF-8");
                        View v;
                        v =(View) result;
                        jamjun.infra.web.CHelper.View(v.getView_name(), request, response, v.getModel());
                    }else if(result.getResultType() == ResultType.content){
                        response.setContentType("text/html;charset=UTF-8");
                        Content c;
                        c =(Content) result;
                        PrintWriter out = response.getWriter();
                        out.print(c.getContentString());
                    }else if(result.getResultType() == ResultType.json){
                        response.setContentType("application/json;charset=UTF-8");
                        PrintWriter out = response.getWriter();
                        Json j;
                        j =(Json) result;
                        Gson gson = new Gson();
                        String json = gson.toJson(j.getObj());
                        out.write(json);
                    }else if(result.getResultType() == ResultType.file){

                    }
                }
                //processRequest(request, response);
        }
        catch(Exception e)
        {
            //e.printStackTrace();
            PrintWriter out = response.getWriter();
            out.print(e.toString());
        }
    }
}


